<template>
  <div>
    <h1>多人视频通话</h1>
    <div>
      <input v-model="roomId" placeholder="请输入房间号" ref="input" />
    </div>
    <div>
      <video
        style="width: 400px; height: 300px"
        ref="localVideo"
        autoplay
      ></video>
    </div>
    <video
      style="width: 400px; height: 300px"
      ref="otherVideo"
      autoplay
    ></video>
    <!-- <br />
    <button @click="test()">测试功能</button> -->
    <br />
    <button @click="connectWebSocket()">测试连接</button>
    <br />
    <button @click="getMediaDevices()">获取本地媒体</button>
    <br />
    <button @click="addLocalStreamToRtcConnection()">
      将本地视频添加到RTC连接中
    </button>
    <br />
    <br />
    <button @click="createRtcConnection()">创建RTC连接</button>
    <br />
    <button @click="createOffer()">创建offer</button>
    <br />
    <textarea v-model="currentText" />
    <br />
    <button @click="setRemoteDescription()">设置远程描述</button>
    <br />
    <button @click="createAnswer()">创建Answer</button>
    <br />
    <button @click="addCandidate()">添加候选</button>
    <br />
  </div>
</template>

<script>
export default {
  data() {
    return {
      // 定义本机运行的IP地址
      ip: "192.168.8.115",
      userId: new Date().getTime(),
      // 房间号
      roomId: 123,
      targetUid: "",

      // websocket对象
      socket: {},

      // 如果两台服务器无法点对点连接，则会使用中继服务器来通信
      rtcPcParams: {
        iceServers: [{ urls: "stun:stun.l.google.com:19302" }],
      },
      // rtc对象
      rtcConnection: {},

      // 文本信息
      currentText: "",

      // 本地视频流对象
      localStream: {},
      // 其它视频流对象
      otherStreamList: [],

      // 控制是否启用或者禁用和启用视频和音频
      useVideo: true,
      useAudio: false,

      // 保存sdp
      offer: {},
      answer: {},
      // 保存候选地址
      candidateList: [],
    };
  },
  async created() {
    // 建立和后端的WebSocket连接
    // this.connectWebSocket();
    this.rtcConnectInit();
  },
  methods: {
    // 获取WebSocket连接
    connectWebSocket() {
      // yxx房间号
      this.socket = new WebSocket(
        `wss://${this.ip}:8087/signal/${this.roomId}/${this.userId}/0`
      );
      // 回调方法
      // this.socket.onopen = this.onSocketOpen;
      // this.socket.onmessage = this.onSocketMessage;
      // this.socket.onclose = this.onSocketClose;
      // this.socket.onerror = this.onSocketError;
    },

    // WebSocket消息事件，服务器返回的消息
    async onSocketMessage(event) {
      const message = JSON.parse(event.data);
      console.log("打印WebSocket消息事件信息", message);

      // 当后端返回type为join的信息时，查询房间还有多少人，
      // 当后端返回type为join的信息时，记录此人，发送offer给它
      if (message.type == "join") {
        // let sendObj = JSON.stringify({
        //   type: "roomUserList",
        //   roomId: this.roomId,
        // });
        // this.socket.send(sendObj);
        if (message.data.userId != this.userId) {
          this.targetUid = message.data.userId;
          await this.myCreateOffer();
          let sendObj = JSON.stringify({
            type: "offer",
            targetUid: message.data.userId,
            userId: this.userId,
            offer: this.offer,
          });
          this.socket.send(sendObj);
        }
      } else if (message.type == "roomUserList") {
        console.log("打印roomUserList结果", message);
        // 除了自己外，和其它人建立连接
        message.data.forEach(async (i) => {
          if (i.userId != this.userId) {
            this.targetUid = i.userId;
            await this.myCreateOffer();
            let sendObj = JSON.stringify({
              type: "offer",
              targetUid: i.userId,
              userId: this.userId,
              offer: this.offer,
            });
            this.socket.send(sendObj);
          }
        });
      } else if (message.type == "offer") {
        console.log("打印接收到的offer", message);
        // 设置接收到的offer为远程描述，发送answer
        this.mySetRemoteDescription(JSON.stringify(message.data.offer));

        // 初始化回答
        await this.myCreateAnswer();
        // 发送回答
        let sendObj = JSON.stringify({
          type: "answer",
          targetUid: message.data.userId,
          userId: this.userId,
          offer: this.answer,
        });
        this.socket.send(sendObj);
      } else if (message.type == "answer") {
        console.log("打印answer结果", message);
        // 将回答放入到远程描述中
        this.mySetRemoteDescription(JSON.stringify(message.data.offer));
      } else if (message.type == "candidate") {
        // 添加candidate
        console.log("获取到了candidate", message);
        // console.log("this.candidateList", this.candidateList);

        this.myAddCandidate(JSON.stringify(message.data.candidate));
      }
    },

    // 发送socket消息
    sendSocketMessage(message) {
      // 确保WebSocket连接已经打开
      if (this.socket && this.socket.readyState === WebSocket.OPEN) {
        // 使用send方法发送消息
        this.socket.send(message);
      } else {
        console.error("WebSocket连接尚未打开或已关闭");
      }
    },

    // yxx测试方法
    test() {
      // 获取设备媒体视频
      this.getMediaDevices();
      // 创建RTC连接
      this.createRtcConnection();
      // 将本地视频流添加到RTC中
      this.addLocalStreamToRtcConnection();

      this.createOffer();
    },

    // testJoin() {

    // },
    // rct连接方法
    async rtcConnectInit() {
      // 获取设备媒体视频
      await this.getMediaDevices();
      console.log("-----------------");
      // 创建RTC连接
      this.createRtcConnection();
      // 将本地视频流添加到RTC中
      this.addLocalStreamToRtcConnection();
      // 创建offer
      // this.createOffer();
      // socket中去发送消息给后端
    },

    // 获取设备视频
    async getMediaDevices() {
      try {
        const stream = await navigator.mediaDevices.getUserMedia({
          video: true,
          audio: true,
        });
        console.log("成功获取本地媒体信息");
        this.$refs.localVideo.srcObject = stream;
        // 保存获取摄像头时拿到的媒体流
        this.localStream = stream;
      } catch (error) {
        console.error("获取媒体设备失败", error);
      }
    },

    // 创建RTC连接
    createRtcConnection() {
      let rtc = new RTCPeerConnection(this.rtcPcParams);

      // 交换候选地址
      rtc.onicecandidate = (e) => {
        if (e.candidate) {
          this.candidateList.push(e.candidate);
          // // 发送出去
          // let sendObj = JSON.stringify({
          //   type: "candidate",
          //   targetUid: this.targetUid,
          //   userId: this.userId,
          //   candidate: e.candidate,
          // });
          // this.socket.send(sendObj);
          console.log("candidate", JSON.stringify(e.candidate));
        }
      };

      // 处理onTrack回调，接收到远程的媒体流时触发
      rtc.ontrack = (e) => {
        this.$refs.otherVideo.srcObject = e.streams[0];
      };
      this.rtcConnection = rtc;
      console.log("rtc创建成功", this.rtcConnection);
    },

    // 创建offer，创建会话描述协议sdp，双方需要互相交换sdp
    createOffer() {
      this.rtcConnection
        .createOffer({
          offerToReceiveVideo: true,
          offerToReceiveAudio: true,
        })
        .then((sdp) => {
          // 存储sdp
          this.offer = sdp;
          console.log("offer的spd为", JSON.stringify(sdp));
          this.rtcConnection.setLocalDescription(sdp);
        });
    },

    // yxx
    async myCreateOffer() {
      let spd = await this.rtcConnection.createOffer({
        offerToReceiveVideo: true,
        offerToReceiveAudio: true,
      });
      // 存储sdp
      this.offer = spd;
      console.log("offer的spd为", JSON.stringify(spd));
      this.rtcConnection.setLocalDescription(spd);
    },

    // 设置远程描述
    setRemoteDescription() {
      const remoteSdp = JSON.parse(this.currentText);
      this.rtcConnection.setRemoteDescription(
        new RTCSessionDescription(remoteSdp)
      );
      console.log("设置远程描述成功", remoteSdp);
    },

    // yxx我的设置远程描述
    mySetRemoteDescription(currentText) {
      const remoteSdp = JSON.parse(currentText);
      this.rtcConnection.setRemoteDescription(
        new RTCSessionDescription(remoteSdp)
      );
      console.log("设置远程描述成功", remoteSdp);
    },

    // 创建Answer
    createAnswer() {
      this.rtcConnection
        .createAnswer({
          offerToReceiveVideo: true,
          offerToReceiveAudio: true,
        })
        .then((sdp) => {
          this.answer = sdp;
          console.log("answer的spd为", JSON.stringify(sdp));
          this.rtcConnection.setLocalDescription(sdp);
        });
    },

    // yxx
    async myCreateAnswer() {
      let sdp = await this.rtcConnection.createAnswer({
        offerToReceiveVideo: true,
        offerToReceiveAudio: true,
      });
      this.answer = sdp;
      console.log("answer的spd为", JSON.stringify(sdp));
      this.rtcConnection.setLocalDescription(sdp);
    },

    // 添加候选地址
    addCandidate() {
      let candidate = JSON.parse(this.currentText);
      this.rtcConnection.addIceCandidate(new RTCIceCandidate(candidate));
      console.log("添加候选成功", candidate);
    },

    // yxx添加候选
    myAddCandidate(currentText) {
      let candidate = JSON.parse(currentText);
      this.rtcConnection.addIceCandidate(new RTCIceCandidate(candidate));
      console.log("添加候选成功", candidate);
    },

    // 将本地视频流添加到RTC中
    addLocalStreamToRtcConnection() {
      this.localStream.getTracks().forEach((track) => {
        this.rtcConnection.addTrack(track, this.localStream);
      });
      console.log("将本地视频流添加到RTC连接成功");
    },
  },
};
</script>
